import time, json, random
from django.conf import settings
from django.forms.models import model_to_dict
from django.db import transaction
from rest_framework import viewsets
from rest_framework import serializers
from rest_framework.serializers import *
from rest_framework.response import Response
from rest_framework.validators import UniqueValidator, UniqueTogetherValidator  # 验证器

from iClouds.apidev import filter_views
from iClouds.Permissions import (
    OR,
    AllPermissions,
    MyPermissions,
    BoxPermissions,
    WeChatPermissions,
    BarPermissions,
)
from iClouds.Authentication import (
    MyJWTAuthentication,
    BoxJWTAuthentication,
    WeChatJWTAuthentication,
    BarJWTAuthentication,
)
from VipManager.serializers import AllinpayMemberListSerializer
from mysqldb import redis as REDIS
from mysqldb.models import *

from .FilterBackends import *


class NoneSerializer(serializers.Serializer):
    """无请求参数"""

    class Meta:
        fields = "__all__"


class AllinpayPlaceRangeSerializer(serializers.ModelSerializer):
    """场所编码转换"""

    id = IntegerField(label="ID", read_only=True)
    barcode = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=True
    )
    bartype = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=True
    )
    pid = IntegerField(allow_null=True, required=True)

    class Meta:
        model = AllinpayPlaceRange
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=AllinpayPlaceRange.objects.all(),
                fields=("barcode", "bartype"),
            )
        ]


# ---------------------------------------------
# class FsygPcListSerializer(serializers.Serializer):
#     """凡商PC列表"""

#     id = IntegerField(label="ID", read_only=True)
#     barid = CharField(
#         allow_blank=True,
#         allow_null=True,
#         max_length=255,
#         required=True,
#         help_text="场所编码",
#     )
#     # bartype = ChoiceField(
#     #     allow_blank=True,
#     #     allow_null=True,
#     #     choices=settings.ALL_CODE_RANGE,
#     #     help_text=f"编码类型 {[i for i in settings.ALL_CODE_RANGE]}",
#     # )
#     name = CharField(
#         allow_blank=True,
#         allow_null=True,
#         max_length=255,
#         required=True,
#         help_text="计算机名",
#     )
#     group = CharField(
#         allow_blank=True,
#         allow_null=True,
#         max_length=255,
#         required=False,
#         help_text="区域",
#     )
#     mac = CharField(
#         allow_blank=True,
#         allow_null=True,
#         max_length=255,
#         required=False,
#         help_text="MAC地址",
#     )
#     ipaddr = IPAddressField(
#         protocol="ipv4",
#         required=False,
#         help_text="IP地址",
#     )
#     mask = IPAddressField(
#         protocol="ipv4",
#         required=False,
#         help_text="子网掩码",
#     )
#     gateway = IPAddressField(
#         protocol="ipv4",
#         required=False,
#         help_text="网关",
#     )
#     dns1 = IPAddressField(
#         protocol="ipv4",
#         required=False,
#         help_text="DNS主",
#     )
#     dns2 = IPAddressField(
#         protocol="ipv4",
#         required=False,
#         help_text="DNS备",
#     )
#     status = IntegerField(
#         allow_null=True,
#         max_value=1,
#         min_value=0,
#         default=1,
#         help_text="状态: 0 停用; 1 启用",
#     )
#     lasttime = DateTimeField(
#         read_only=True, allow_null=True, required=False, help_text="登录时间"
#     )

#     class Meta:
#         model = FsygPcList
#         fields = "__all__"


class FsygReportDataV2Serializer(serializers.Serializer):
    """凡商云购上机数据V2"""

    barid = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="场所编码",
    )
    name = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="计算机名",
    )
    data = DictField(
        child=CharField(allow_blank=True, allow_null=True), help_text="数据字段(JSON)"
    )

    class Meta:
        fields = "__all__"


# class FsygReportDataSerializer(serializers.Serializer):
#     """凡商云购上机数据"""

#     barid = CharField(
#         allow_blank=True,
#         allow_null=True,
#         max_length=255,
#         required=True,
#         help_text="场所编码",
#     )
#     name = CharField(
#         allow_blank=True,
#         allow_null=True,
#         max_length=255,
#         required=True,
#         help_text="计算机名",
#     )
#     hash = CharField(
#         allow_blank=True,
#         allow_null=True,
#         max_length=255,
#         required=False,
#         help_text="会员hash码",
#     )
#     gerder = IntegerField(
#         allow_null=True,
#         max_value=1,
#         min_value=0,
#         default=0,
#         help_text="会员性别： 0 女; 1 男",
#     )
#     birthday = DateField(allow_null=True, required=False, help_text="会员生日")
#     money = IntegerField(allow_null=True, default=0, help_text="会员当前余额(分)")
#     lasttime = DateTimeField(allow_null=True, required=False, help_text="本次上机时间")
#     status = IntegerField(
#         allow_null=True,
#         max_value=1,
#         min_value=0,
#         default=3,
#         help_text="状态: 0 停用; 1 上机中; 2 清洁中; 3 待机中",
#     )

#     class Meta:
#         fields = "__all__"


class FsygHasWorkSerializer(serializers.Serializer):
    """凡商云购查询上机数据"""

    barid = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="场所编码",
    )
    # bartype = ChoiceField(
    #     allow_blank=True,
    #     allow_null=True,
    #     choices=settings.ALL_CODE_RANGE,
    #     help_text=f"编码类型 {[i for i in settings.ALL_CODE_RANGE]}",
    # )

    class Meta:
        fields = "__all__"


# =========================================================
class FsygWorksGroupSerializer(serializers.Serializer):
    """手动请求场所终端分组数据"""

    wb_id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="网吧id",
    )

    class Meta:
        fields = "__all__"


# =========================================================
class FsygAlertSerializer(serializers.Serializer):
    """触发消息推送"""

    act = ChoiceField(
        choices=("上机信息", "用户信息", "区域/费率信息", "计费消费记录", "商品订单查询", "商品退单查询"), required=True
    )
    wb_id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="网吧id",
    )
    id_card_hash = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text='身份证MD5大写 临时卡前缀带有 " - "',
    )
    start_time = DateField(required=False)
    end_time = DateField(required=False)
    page = IntegerField(default=1)

    class Meta:
        fields = "__all__"


class FsygProgrunListSerializer(serializers.Serializer):
    """凡商上下机推送通知"""

    id = IntegerField(label="ID", read_only=True)
    message_type = ChoiceField(choices=("machine_up", "machine_down"), required=True)
    wb_id = CharField(allow_blank=True, allow_null=True, max_length=255, required=True)

    card_id = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    guid = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        # validators=[UniqueValidator(queryset=FsygProgrunList.objects.all())],
    )
    computer_name = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=True
    )

    flag = IntegerField(
        allow_null=True, max_value=2147483647, min_value=-2147483648, required=False
    )
    amount = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    memo = CharField(allow_blank=True, allow_null=True, max_length=255, required=False)
    down_time = DateTimeField(allow_null=True, required=False)

    on_time = DateTimeField(allow_null=True, required=False)
    on_day = DateField(allow_null=True, required=False)
    down_day = DateField(allow_null=True, required=False)

    class Meta:
        # model = FsygProgrunList
        fields = "__all__"


class FsygShopintoListSerializer(serializers.ModelSerializer):
    """商品流水"""

    class Meta:
        model = FsygShopintoList
        fields = "__all__"


class FsygMemberListSerializer(serializers.ModelSerializer):
    """凡商会员"""

    class Meta:
        model = FsygMemberList
        fields = "__all__"


class FsygShopreqsnListSerializer(serializers.ModelSerializer):
    """订单流水"""

    id = IntegerField(label="ID", read_only=True)
    reqsn = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        validators=[UniqueValidator(queryset=FsygShopreqsnList.objects.all())],
    )
    temp_order_id = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    message_type = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    wb_id = CharField(allow_blank=True, allow_null=True, max_length=255, required=False)
    wb_name = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    maid = CharField(allow_blank=True, allow_null=True, max_length=255, required=False)
    create_time = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    pay_time = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    pay_type = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    amount = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    machine_no = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    notes = CharField(allow_blank=True, allow_null=True, max_length=255, required=False)
    order_type = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    order_status = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    syy_name = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    syy_uid = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    salesman = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    sales_uid = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    refund_amount = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    refund_man = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    refund_uid = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    refund_source = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )
    order_id = CharField(
        allow_blank=True, allow_null=True, max_length=255, required=False
    )

    products = SerializerMethodField()
    callme = SerializerMethodField()

    class Meta:
        model = FsygShopreqsnList
        fields = "__all__"

    def has_Staff_Info(self, sid):
        """查询员工信息"""
        try:
            r = AllinpayStaffList.objects.get(id=sid)
        except BaseException as err:
            return None
        else:
            return {"id": r.id, "basename": r.basename, "nicename": r.nicename}

    def get_products(self, attr):
        r = FsygShopintoList.objects.filter(order=attr.reqsn)
        return FsygShopintoListSerializer(r, many=True).data

    def get_callme(self, attr):
        try:
            r = AllinpayCallmeList.objects.get(bem=attr.id)
        except BaseException as err:
            return None
        else:
            return {
                "id": r.id,
                "reqsn": r.reqsn,
                "area": r.area,
                "source": r.source,
                "status": r.status,
                "le1": r.le1,
                "le1k": r.le1k,
                "target": self.has_Staff_Info(r.target),
            }


# print(repr(FsygShopreqsnListSerializer()))


# =======================================================================
class ThisShopListSerializer(serializers.ListField):
    """商品列表"""

    categorize = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="商品分类",
    )
    product_name = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="商品名称",
    )
    original_price = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="商品售价",
    )
    price = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="商品支付价格",
    )
    cost = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="商品成本",
    )
    count = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=True,
        help_text="购买数量",
    )


# ===============================================================
class ThisFsygShopreqsnListSerializer(serializers.Serializer):
    """商品售卖单"""

    message_type = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="消息类型固定值(order,refund)",
    )
    wb_id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        help_text="易购网吧id",
    )

    id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="订单号",
    )
    temp_order_id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="临时单号",
    )

    wb_name = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="网吧名称",
    )
    create_time = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="订单创建时间",
    )
    pay_time = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="订单支付时间",
    )
    pay_type = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="支付方式 0=未支付,1=微信,2=支付宝,3=翼支付,5=余额,6=积分,7=移动积分,8=分期超人,9=现金",
    )
    amount = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="销售金额",
    )
    machine_no = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="机器号",
    )
    notes = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="备注",
    )
    order_type = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="订单来源 0=C端订单,1=吧台订单,2=网管代下单,3=无人货架订单,4=交班补单,5=积分订单,6=外卖订单,7=公众号充值网费",
    )
    order_status = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="订单状态 -3=取消订单,-2=支付失败,-1=二维码创建失败,0=新订单,1=已支付,2=已完成",
    )
    syy_name = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="收银员",
    )
    syy_uid = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="收银员id",
    )
    salesman = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="销售员",
    )
    sales_uid = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="销售员id",
    )
    refund_amount = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="退款金额",
    )
    refund_man = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="退款人",
    )
    refund_uid = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="退款人id",
    )
    refund_source = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="退款来源 0 管理后台 1收银端",
    )
    order_id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="原始订单号",
    )
    products = ThisShopListSerializer(
        allow_empty=True, min_length=None, max_length=None, help_text="商品队列"
    )

    class Meta:
        fields = "__all__"

    # callme = SerializerMethodField()
    # def get_callme(self, attr):
    #     try:
    #         r = AllinpayCallmeList.objects.get(bem=attr.id)
    #     except BaseException as err:
    #         return None
    #     else:
    #         return {
    #             "id": r.id,
    #             "reqsn": r.reqsn,
    #             "area": r.area,
    #             "source": r.source,
    #             "status": r.status,
    #             "le1": r.le1,
    #             "le1k": r.le1k,
    #             "target": self.has_Staff_Info(r.target),
    #         }
    # def has_Staff_Info(self, sid):
    #     """查询员工信息"""
    #     try:
    #         r = AllinpayStaffList.objects.get(id=sid)
    #     except BaseException as err:
    #         return None
    #     else:
    #         return {"id": r.id, "basename": r.basename, "nicename": r.nicename}


# ============================================================================
class ThisFsygDataRecvSendSerializer(serializers.Serializer):
    """凡商触发推送消息序列化"""

    message_type = ChoiceField(
        allow_blank=True,
        choices=(
            ("user_info", "上机信息"),
            ("query_member", "用户信息"),
            ("query_rate", "区域信息"),
            ("consumed_record", "消费记录"),
            ("order", "商品订单"),
            ("refund", "商品退单"),
            ("machine_up", "上机推送"),
            ("machine_down", "下机推送"),
            ("machine_change", "换机推送"),
            ("server", "收银机上线"),
            ("apartment", "门店信息推送"),
            ("staff_save", "员工信息变更"),
            ("staff_delete", "员工信息删除"),
        ),
        help_text="消息类型固定值",
    )
    wb_id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="场所编码",
    )
    data = JSONField(required=False, help_text="数据字段(JSON)")
    # 上线
    card_id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="网吧编码",
    )
    guid = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="上机标识",
    )
    computer_name = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="机器号",
    )
    # 下线
    flag = IntegerField(
        allow_null=True,
        max_value=2147483647,
        min_value=-2147483648,
        required=False,
        help_text="标记",
    )
    amount = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="下机未知，订单金额",
    )
    memo = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="备注",
    )
    down_time = DateTimeField(allow_null=True, required=False, help_text="下机时间")
    # 商品订单
    id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="订单号",
    )
    temp_order_id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="临时单号",
    )

    wb_name = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="网吧名称",
    )
    create_time = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="订单创建时间",
    )
    pay_time = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="订单支付时间",
    )
    pay_type = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="支付方式 0=未支付,1=微信,2=支付宝,3=翼支付,5=余额,6=积分,7=移动积分,8=分期超人,9=现金",
    )

    machine_no = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="机器号",
    )
    notes = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="备注",
    )
    order_type = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="订单来源 0=C端订单,1=吧台订单,2=网管代下单,3=无人货架订单,4=交班补单,5=积分订单,6=外卖订单,7=公众号充值网费",
    )
    order_status = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="订单状态 -3=取消订单,-2=支付失败,-1=二维码创建失败,0=新订单,1=已支付,2=已完成",
    )
    syy_name = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="收银员",
    )
    syy_uid = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="收银员id",
    )
    salesman = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="销售员",
    )
    sales_uid = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="销售员id",
    )
    refund_amount = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="退款金额",
    )
    refund_man = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="退款人",
    )
    refund_uid = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="退款人id",
    )
    refund_source = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="退款来源 0 管理后台 1收银端",
    )
    order_id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="原始订单号",
    )
    products = JSONField(required=False, help_text="商品列表(JSON)")
    # 换机数据
    from_card_id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="源身份识别码",
    )
    from_computer = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="源机号",
    )
    to_card_id = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="目标身份识别码",
    )
    to_computer = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="目标机号",
    )

    class Meta:
        fields = "__all__"


class AllinpayCallmeCreatSerializer(serializers.ModelSerializer):
    """创建呼叫"""

    class Meta:
        model = AllinpayCallmeList
        fields = "__all__"


class FsygMemberLevelSerializer(serializers.ModelSerializer):
    """会员等级"""

    id = IntegerField(label="ID", read_only=True)
    wbcode = CharField(
        allow_blank=True, allow_null=True, max_length=255, help_text="场所ID"
    )
    name = CharField(
        allow_blank=True, allow_null=True, max_length=255, help_text="等级名称"
    )
    level = ChoiceField(choices=(1, 2, 3, 4, 5, 6), help_text="会员等级")

    class Meta:
        model = FsygMemberLevel
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=FsygMemberLevel.objects.all(), fields=("wbcode", "level")
            )
        ]


# print(repr(FsygMemberLevelSerializer()))
